﻿@namespace BlazorDemos.Shared
@implements IDisposable;

<div class="@classNames" role="tree">
    <ul class="@SampleUtils.TREE_PARENT" role="tree">
        @foreach (var components in this.DataSource)
        {
            <li class="@SampleUtils.TREE_PARENT_LI" role="treeitem">
                @{
                    var classList = GetClassList(components);
                }
                <div class="@SampleUtils.TREE_FULL_ROW" @onclick="@(() => OnParentClick(components))"></div>
                <div class="@SampleUtils.TREE_TEXT_CONTENT">
                    <div class="@classList["iconClass"]" @onclick="@(() => OnParentClick(components))"></div>
                    <span class="@SampleUtils.TREE_TEXT">@components.Name</span>
                </div>
                <ul class="@classList["childClass"]" role="group">
                    @foreach (var component in components.SourceData)
                    {
                        <li class="@SampleUtils.TREE_PARENT_LI" role="treeitem">
                            @{
                                var nodeFullRow = SampleUtils.TREE_FULL_ROW;
                                if (EqualityComparer<SampleListType>.Default.Equals(component, childSelected))
                                {
                                    nodeFullRow = SampleUtils.AddClass(nodeFullRow, SampleUtils.TREE_ACTIVE);
                                }
                            }
                            <div class="@nodeFullRow" @onclick="@(async () => await OnChildClick(component))"></div>
                            <div class="@SampleUtils.TREE_TEXT_CONTENT">
                                <span class="@SampleUtils.TREE_TEXT">
                                    @TreeTemplate(component)
                                </span>
                            </div>
                        </li>
                    }
                </ul>
            </li>
        }
    </ul>
</div>

@code {
    private SampleListType childSelected;
    private List<SampleListType> collapsedItems = new List<SampleListType>();
    private string classNames = SampleUtils.TREE_CLASS + SampleUtils.SPACE + SampleUtils.TREE_HIDE;

    /// <summary>
    /// Child content of tree component.
    /// </summary>
    [Parameter]
    public RenderFragment ChildContent { get; set; }

    /// <summary>
    /// Specifies the datasource of the tree component.
    /// </summary>
    [Parameter]
    public IEnumerable<SampleListType> DataSource { get; set; }

    /// <summary>
    /// Specifies the template of the tree component.
    /// </summary>
    [Parameter]
    public RenderFragment<SampleListType> TreeTemplate { get; set; }

    /// <summary>
    /// Triggers the event callback on tree node selection.
    /// </summary>
    [Parameter]
    public EventCallback<SampleListType> OnNodeSelect { get; set; }

    /// <summary>
    /// Show or hide the tree component based on the logic.
    /// </summary>
    /// <param name="isVisible">Specifies the input to show or hide the component.</param>
    public void ShowTree(bool isVisible = true)
    {
        if (isVisible)
        {
            classNames = SampleUtils.RemoveClass(classNames, SampleUtils.TREE_HIDE);
        }
        else
        {
            classNames = SampleUtils.AddClass(classNames, SampleUtils.TREE_HIDE);
        }
        StateHasChanged();
    }

    /// <summary>
    /// Select the tree node based on given node data.
    /// </summary>
    /// <param name="nodeItem">Specifies the node item need to be selected.</param>
    public void SelectNode(SampleListType nodeItem)
    {
        childSelected = nodeItem;
        StateHasChanged();
    }

    // Parent node selection handler.
    private void OnParentClick(SampleListType parent)
    {
        var itemIndex = collapsedItems.IndexOf(parent);
        if (itemIndex == -1)
        {
            collapsedItems.Add(parent);
        }
        else
        {
            collapsedItems.RemoveAt(itemIndex);
        }
    }

    // Child node selection handler.
    private async Task OnChildClick(SampleListType child)
    {
        childSelected = child;
        if (OnNodeSelect.HasDelegate)
        {
            await OnNodeSelect.InvokeAsync(child);
        }
    }

    // Returns the list of class for current group.
    private Dictionary<string, string> GetClassList(SampleListType components)
    {
        var classList = new Dictionary<string, string>();
        classList["iconClass"] = "sb-icons" + SampleUtils.SPACE + SampleUtils.TREE_EXPAND_ICON;
        classList["childClass"] = SampleUtils.TREE_PARENT;
        if (collapsedItems.Count > 0)
        {
            var collapsed = collapsedItems.Where(item => item.Name == components.Name).ToList();
            if (collapsed.Count > 0)
            {
                classList["iconClass"] = SampleUtils.RemoveClass(classList["iconClass"], SampleUtils.TREE_EXPAND_ICON);
                classList["iconClass"] = SampleUtils.AddClass(classList["iconClass"], SampleUtils.TREE_COLLAPSE_ICON);
                classList["childClass"] = SampleUtils.AddClass(classList["childClass"], SampleUtils.DISPLAY_NONE);
            }
        }
        return classList;
    }

    public void Dispose()
    {
        childSelected = null;
        collapsedItems = null;
        DataSource = null;
    }
}
